package com.ruoyi.oauth.sso;

import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.oauth.domain.OauthClient;
import com.ruoyi.oauth.domain.OauthToken;
import com.ruoyi.oauth.service.IOauthLogService;
import com.ruoyi.oauth.sso.service.IOauthService;
import com.ruoyi.oauth.sso.vo.AccessToken;
import com.ruoyi.oauth.sso.vo.OAuthRequest;
import com.ruoyi.oauth.sso.vo.UserDetail;
import com.ruoyi.oauth.utils.OAuthUtil;
import com.ruoyi.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.stream.Collectors;

/**
 * @author yepanpan
 * @date 2024/1/11 11:42
 */
@RestController
@RequestMapping("/oauth2")
public class TokenController {
    private static final Logger log = LoggerFactory.getLogger(AuthorizeController.class);
    @Autowired
    IOauthService oauthService;
    @Autowired
    ISysUserService userService;
    @Autowired
    IOauthLogService oauthLogService;

    /**
     * 获取令牌
     * @param model
     * @param request
     * @return
     */
    @PostMapping(value = "/token")
    public Object token(Model model, HttpServletRequest request){
        OAuthRequest tokenRequest;
        Object ret = null;
        OauthToken token = null;
        String state = "0";
        try {
            tokenRequest = new OAuthRequest(request);

            OauthClient oauthClient = oauthService.checkClient(model, tokenRequest.getClientId());
            if (oauthClient == null) {
                throw new ServiceException("不支持客户端");
            }else if(!oauthClient.getClientSecret().equals(tokenRequest.getClientSecret())){
                throw new ServiceException("校验客户端失败");
            }

            GrantType grantType = GrantType.valueOf(request.getParameter(OAuthUtil.OAUTH_GRANT_TYPE).toUpperCase());
            switch (grantType) {
                case AUTHORIZATION_CODE:
                    token = oauthService.code2Token(request, tokenRequest);
                    break;
                case REFRESH_TOKEN:
                    token = oauthService.refresh2Token(request);
                    break;
                case PASSWORD:
                    token = oauthService.pwd2Token(request, tokenRequest);
                    break;
                case CLIENT_CREDENTIALS:
                    token = oauthService.secret2Token(request, tokenRequest);
                    break;
                default:
                    throw new ServiceException("不支持的认证模式");
            }
            //返回令牌信息
            AccessToken accessToken = new AccessToken();
            accessToken.setAccess_token(token.getAccessToken());
            accessToken.setRefresh_token(token.getRefreshToken());
            accessToken.setExpires_in(token.getExpiredTime().getTime() / 1000);
            ret = accessToken;
        }catch (Exception e){
            state = "1";
            ret = new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
            log.error("获取令牌失败: {}", e);
        }
        //记录日志
        oauthService.log(token == null? null: token.getClientId(), token == null? null:token.getUserName(), "获取令牌",
                request.getRemoteHost(), token == null? null:token.getAccessToken(), request.getQueryString(), state);

        return ret;
    }

    /**
     * 根据令牌，获取用户的详细信息
     * @param request
     * @return
     */
    @GetMapping(value = "/detail")
    public Object detail(HttpServletRequest request) {
        Object ret = null;
        OauthToken oauthToken = null;
        String state = "0";
        try {
            oauthToken = oauthService.checkToken(request);
            if (oauthToken != null) {
                SysUser user = userService.selectUserByUserName(oauthToken.getUserName());
                UserDetail userDetail = new UserDetail();
                userDetail.setUserId(user.getUserId());
                userDetail.setNickName(user.getNickName());
                userDetail.setUserName(user.getUserName());
                userDetail.setDeptId(user.getDeptId());
                if (user.getDept() != null) {
                    userDetail.setDeptName(user.getDept().getDeptName());
                }
                if (user.getRoles() != null && !user.getRoles().isEmpty()) {
                    userDetail.setRoleIds(user.getRoles().stream().map(r -> r.getRoleKey()).collect(Collectors.joining(",")));
                }
                ret  = userDetail;
            }else{
                state = "1";
                ret = new ResponseEntity(HttpStatus.UNAUTHORIZED);
            }
        }catch (Exception e){
            log.error("获取用户信息失败: {}", e);
            ret = new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
        }
        //记录日志
        oauthService.log(oauthToken == null? null: oauthToken.getClientId(), oauthToken == null? null:oauthToken.getUserName(), "获取用户信息",
                request.getRemoteHost(), oauthToken == null? null:oauthToken.getAccessToken(), request.getQueryString(), state);
        return ret;
    }
}
